package com.css.fxfzmhwz.util;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;


import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class AreaBoundaryUtil {

    public static String amapKey = "b2b9885cc527dffb695aab49a57fd550";

    public static Map<String, Map<String, Map<String, String>>> dataStore = new HashMap<String, Map<String, Map<String, String>>>();
    public static Map<String, Map<String, String>> province2boundary = new HashMap<String, Map<String, String>>();
    public static Map<String, Map<String, String>> province2citiesBoundary = new HashMap<String, Map<String, String>>();

    /*public static void initialize (String pcaPath, String pPath, String pcPath) {
        File file = new File(pcaPath);
        if(!ArrayUtils.isEmpty(file.listFiles())){
            dataStore = readAllAreasByCountry(file.getAbsolutePath());
            for (File f : file.listFiles()) {
                log.info(f.getAbsolutePath());
            }
        }else {
            log.info("未获取到区县边界数据文件！");
        }

        File province_file = new File(pPath);
        if(!ArrayUtils.isEmpty(province_file.listFiles())){
            province2boundary = readAllProvincesBoundary(province_file.getAbsolutePath());
        }else{
            log.info("未获取到省边界数据文件！");
        }

        File province_city_file = new File(pcPath);
        if(!ArrayUtils.isEmpty(province_city_file.listFiles())){
            province2citiesBoundary = readAllProvinces2citiesBoundary(province_city_file.getAbsolutePath());
        }else{
            log.info("未获取到市边界数据文件！");
        }
    }*/

    public static String doGet(String httpurl) {
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedReader br = null;
        String result = null;
        try {
            URL url = new URL(httpurl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(15000);
            connection.setReadTimeout(60000);
            connection.connect();
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                StringBuffer sbf = new StringBuffer();
                String temp = null;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append("\r\n");
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != br) br.close();
                if (null != is) is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            connection.disconnect();
        }
        return result;
    }

    /**
     * 以【中国】为键, 获取全国区县边界
     * 格式:
     * {
     * 中国: {
     * 北京市：{
     * 北京市: {
     * 朝阳区: 经纬度串,
     * 海淀区：经纬度串,
     * ...
     * }
     * },
     * 山东省: {
     * 济南市: {
     * 历下区: 经纬度串,
     * ...
     * }
     * },
     * ...
     * }
     * }
     *
     * @param
     */
    public static Map<String, Map<String, Map<String, Map<String, String>>>> getAreaCoordsByCountry() {
        Map<String, Map<String, Map<String, Map<String, String>>>> result = new HashMap<String, Map<String, Map<String, Map<String, String>>>>();
        result.put("中国", getAllProvinces());
        return result;
    }

    /**
     * 以【省份名称】为键, 对应格式二级数据
     *
     * @param
     */
    public static Map<String, Map<String, Map<String, String>>> getAllProvinces() {
        Map<String, Map<String, Map<String, String>>> province2cities = new HashMap<String, Map<String, Map<String, String>>>();
        String httpUrl = "https://restapi.amap.com/v3/config/district?keywords=中国&subdistrict=1&key=" + amapKey + "&extensions=base";
        System.out.println("httpUrl: " + httpUrl);
        String resStr = doGet(httpUrl);
        JSONObject json = JSONObject.parseObject(resStr);
        //System.out.println(json);
        String info = json.getString("info");
        if ("OK".equals(info)) {
            String adcode, name;
            JSONArray provinces = json.getJSONArray("districts").getJSONObject(0).getJSONArray("districts");
            //for(int i = 0;i < provinces.size();i++) {
            for (int i = 0; i < 5; i++) {
                adcode = provinces.getJSONObject(i).getString("adcode");
                name = provinces.getJSONObject(i).getString("name");
                //System.out.println(adcode + "---" + name);
                Map<String, Map<String, String>> res = getAllCitiesByAdcode(adcode, name);
                province2cities.put(name, res);
            }
        }
        return province2cities;
    }

    /**
     * 以【城市名称】为键, 对应格式三级数据
     *
     * @param adcode
     * @param provinceName
     */
    public static Map<String, Map<String, String>> getAllCitiesByAdcode(String adcode, String provinceName) {
        Map<String, Map<String, String>> city2areas = new HashMap<String, Map<String, String>>();
        String path = "https://restapi.amap.com/v3/config/district?keywords=" + adcode + "&subdistrict=1&key=" + amapKey + "&extensions=base";
        System.out.println("httpUrl: " + path);
        String res = doGet(path);
        JSONObject json = JSONObject.parseObject(res);
        //System.out.println(json);
        String info = json.getString("info");
        if ("OK".equals(info)) {
            String _adcode, name;
            JSONArray jArray = json.getJSONArray("districts");
            if (jArray.size() == 0) {
                System.out.println("省份 --> " + provinceName + ": 无城市数据！");
            } else if (jArray.size() == 1) {
                JSONArray cities = jArray.getJSONObject(0).getJSONArray("districts");
                for (int i = 0; i < cities.size(); i++) {
                    _adcode = cities.getJSONObject(i).getString("adcode");
                    name = cities.getJSONObject(i).getString("name");
                    System.out.println(_adcode + "-------" + name);
                    Map<String, String> result = getAllAreasByAdcode(_adcode, name);
                    city2areas.put(name, result);
                }
            } else if (jArray.size() > 1) {
                System.out.println("省份 --> " + provinceName + ": 检索出多条省份数据！");
            }
        }
        return city2areas;
    }

    /**
     * 以【区县名称】为键, 对应格式四级数据
     *
     * @param adcode
     * @param cityName
     */
    public static Map<String, String> getAllAreasByAdcode(String adcode, String cityName) {
        Map<String, String> area2coords = new HashMap<String, String>();
        String path = "https://restapi.amap.com/v3/config/district?keywords=" + adcode + "&subdistrict=1&key=" + amapKey + "&extensions=base";
        System.out.println("httpUrl: " + path);
        String res = doGet(path);
        JSONObject json = JSONObject.parseObject(res);
        //System.out.println(json);
        String info = json.getString("info");
        if ("OK".equals(info)) {
            String _adcode, name, polyline;
            JSONArray jArray = json.getJSONArray("districts");
            if (jArray.size() == 0) {
                System.out.println("城市 --> " + cityName + ": 无区县数据！");
            } else if (jArray.size() == 1) {
                JSONArray districts = jArray.getJSONObject(0).getJSONArray("districts");
                for (int i = 0; i < districts.size(); i++) {
                    _adcode = districts.getJSONObject(i).getString("adcode");
                    name = districts.getJSONObject(i).getString("name");
                    System.out.println(adcode + "=======" + name);
                    //polyline = districts.getJSONObject(i).getString("polyline");
                    polyline = getCoordssByAreaName(_adcode, name);
                    area2coords.put(name, polyline);
                }
            } else if (jArray.size() > 1) {
                System.out.println("城市 --> " + cityName + ": 检索出多条城市数据！");
            }
        }
        return area2coords;
    }

    /**
     * 获取区县对应的边界经纬度
     *
     * @param adcode
     * @param areaName
     */
    public static String getCoordssByAreaName(String adcode, String areaName) {
        String polyline = "";
        String path = "https://restapi.amap.com/v3/config/district?keywords=" + adcode + "&subdistrict=1&key=" + amapKey + "&extensions=all";
        System.out.println("httpUrl: " + path);
        String res = doGet(path);
        JSONObject json = JSONObject.parseObject(res);
        //System.out.println(json);
        String info = json.getString("info");
        if ("OK".equals(info)) {
            JSONArray jArray = json.getJSONArray("districts");
            if (jArray.size() == 0) {
                System.out.println("区县 --> " + areaName + ": 无区县数据！");
            } else if (jArray.size() == 1) {
                polyline = jArray.getJSONObject(0).getString("polyline");
            } else if (jArray.size() > 1) {
                System.out.println("区县 --> " + areaName + ": 检索出多条城市数据！");
            }
        }
        return polyline;
    }

    /**
     * 生成全国所有区域边界
     *
     * @param targetFolder 生成文件存储目录
     */
    public static void writeAllAreasByCountry(String targetFolder) {
        String filePath = "";
        Map<String, Map<String, Map<String, String>>> map = getAllProvinces();
        for (Map.Entry<String, Map<String, Map<String, String>>> entry : map.entrySet()) {
            //System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
            filePath = targetFolder + File.separator + entry.getKey() + ".json";
            writeJsonByProvince(filePath, entry.getValue());
        }
    }

    public static void writeJsonByProvince(String filePath, Map<String, Map<String, String>> province2cities) {
        String jsonString = JSONUtils.toJSONString(province2cities);
        JSONObject object = JSONObject.parseObject(jsonString);
        String pretty = JSON.toJSONString(object, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat);
        try {
            Writer write = new OutputStreamWriter(new FileOutputStream(filePath), "UTF-8");
            write.write(pretty);
            write.flush();
            write.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成单个省份的所有区域边界
     *
     * @param targetFolder 生成文件存储目录
     */
    public static void writeSingleProvinceJson(String targetFolder, String adcode, String provinceName) {
        String filePath = targetFolder + File.separator + provinceName + ".json";
        Map<String, Map<String, String>> map = getAllCitiesByAdcode(adcode, provinceName);
        writeJsonByProvince(filePath, map);
    }

    /**
     * 测试：以省份为一个文件，生成全国区县边界
     *
     * @param targetFolder json文件存储目录
     */
    public static void testWriteCountryJson(String targetFolder) {
        writeAllAreasByCountry(targetFolder);
    }

    /**
     * 测试：生成单个省份区县边界
     *
     * @param targetFolder json文件存储目录
     */
    public static void testWriteSingleProvinceJson(String targetFolder) {
        String adcode = "110000";
        String provinceName = "北京市";
        writeSingleProvinceJson(targetFolder, adcode, provinceName);
    }


    /**
     * 读取全国省份的区县边界
     * {
     * 北京市：{
     * 北京市: {
     * 朝阳区: 经纬度串,
     * 海淀区：经纬度串,
     * ...
     * }
     * },
     * 山东省: {
     * 济南市: {
     * 历下区: 经纬度串,
     * ...
     * }
     * },
     * ...
     * }
     *
     * @param path 存储目录
     */
    /*public static Map<String, Map<String, Map<String, String>>> readAllAreasByCountry(String path) {
        Map<String, Map<String, Map<String, String>>> result = new HashMap<String, Map<String, Map<String, String>>>();
        File file = new File(path);
        File[] fs = file.listFiles();
        if (ArrayUtils.isEmpty(fs)) {
            return null;
        }
        for (File f : fs) {
            if (!f.isDirectory()) {
                String provinceName = f.getName();
                provinceName = provinceName.substring(0, provinceName.length() - 5);
                //System.out.println(provinceName);
                Map<String, Map<String, String>> province2areas = readAllAreasByProvince(provinceName, path);
                result.put(provinceName, province2areas);
            }
        }
        return result;
    }*/

    /**
     * 根据【省份名称】获取区县边界
     *
     * @param provinceName 省份名称
     * @param folder       json文件所在目录
     */
  /*  public static Map<String, Map<String, String>> readAllAreasByProvince(String provinceName, String folder) {
        String provinceJsonFilePath = folder + File.separator + provinceName + ".json";
        Map<String, Map<String, String>> province2areas = null;
        try {
            File file = new File(provinceJsonFilePath);
            String str = FileUtils.readFileToString(file, "UTF-8");
            province2areas = JSONObject.parseObject(str, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return province2areas;
    }*/

    /**
     * 根据【省份名称、城市名称】获取区县边界
     *
     * @param provinceName 省份名称
     * @param cityName     城市名称
     * @param folder       json文件所在目录
     */
    /*public static Map<String, Map<String, String>> readAllAreasByCity(String provinceName, String cityName, String folder) {
        String provinceJsonFilePath = folder + File.separator + provinceName + ".json";
        Map<String, Map<String, String>> city2areas = new HashMap<String, Map<String, String>>();
        try {
            File file = new File(provinceJsonFilePath);
            String str = FileUtils.readFileToString(file, "UTF-8");
            Map<String, Map<String, Map<String, String>>> obj = JSONObject.parseObject(str, Map.class);
            for (Map.Entry<String, Map<String, Map<String, String>>> entry : obj.entrySet()) {
                //System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
                if (cityName.equals(entry.getKey())) {
                    city2areas = entry.getValue();
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return city2areas;
    }*/

    /**
     * 主调函数：根据【省份名称、城市名称、区县名称】获取区县边界
     *
     * @param provinceName 省份名称
     * @param cityName     城市名称
     * @param areaName     区县名称
     * @param folder       json文件所在目录
     */
    /*public static String readCoordsByArea(String provinceName, String cityName, String areaName, String folder) {
        String result = "";
        try {
            String provinceJsonFilePath = folder + File.separator + provinceName + ".json";
            File file = new File(provinceJsonFilePath);
            String str = FileUtils.readFileToString(file, "UTF-8");
            Map<String, Map<String, String>> obj = JSONObject.parseObject(str, Map.class);
            for (Map.Entry<String, Map<String, String>> entry : obj.entrySet()) {
                //System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
                if (cityName.equals(entry.getKey())) {
                    Map<String, String> city2areas = entry.getValue();
                    for (Map.Entry<String, String> _entry : city2areas.entrySet()) {
                        //System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
                        if (areaName.equals(_entry.getKey())) {
                            result = _entry.getValue();
                            break;
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }*/

    /**
     * 主调函数：根据【区县名称】获取区县边界
     *
     * @param areaName 区县名称
     */
    public static String getCoordsByAreaName(String areaName) {
        String result = "";
        //Map<String, Map<String, Map<String, String>>> province2areas = readAllAreasByCountry(folder);
        Map<String, Map<String, Map<String, String>>> province2areas = dataStore;
        for (Map.Entry<String, Map<String, Map<String, String>>> paEntry : province2areas.entrySet()) {
            //System.out.println("key = " + paEntry.getKey() + ", value = " + paEntry.getValue());
            Map<String, Map<String, String>> city2areas = paEntry.getValue();
            for (Map.Entry<String, Map<String, String>> caEntry : city2areas.entrySet()) {
                Map<String, String> area2coords = caEntry.getValue();
                for (Map.Entry<String, String> area2coord : area2coords.entrySet()) {
                    if (areaName.equals(area2coord.getKey())) {
                        result = area2coord.getValue();
                        return result;
                    }
                }
            }
        }
        return result;
    }

    /**
     * 主调函数：根据【区县名称】获取区县边界
     *
     * @param provinceName 省名称
     * @param cityName     城市名称
     */
    public static Map.Entry<String, Map<String, String>> getCoordsByCityName(String provinceName, String cityName) {
        Map.Entry<String, Map<String, String>> result = null;
        //Map<String, Map<String, Map<String, String>>> province2areas = readAllAreasByCountry(folder);
        Map<String, Map<String, Map<String, String>>> province2areas = dataStore;
        for (Map.Entry<String, Map<String, Map<String, String>>> paEntry : province2areas.entrySet()) {
            //System.out.println("key = " + paEntry.getKey() + ", value = " + paEntry.getValue());
            Map<String, Map<String, String>> city2areas = paEntry.getValue();
            for (Map.Entry<String, Map<String, String>> caEntry : city2areas.entrySet()) {
                if (provinceName.equals(paEntry.getKey()) && cityName.equals(caEntry.getKey())) {
                    result = caEntry;
                    return result;
                }
            }
        }
        return result;
    }

    public static void testReadJson(String path) {
        /*
        //获取全国区县边界
        Map<String, Map<String, Map<String, String>>> province2areas = readAllAreasByCountry(path);
        for (Map.Entry<String, Map<String, Map<String, String>>> entry : province2areas.entrySet()) {
            System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
        }*/

        /*
        //根据【省份名称】获取区县边界
        Map<String, Map<String, String>> province2areas = readAllAreasByProvince("广东省", path);
        for (Map.Entry<String, Map<String, String>> entry : province2areas.entrySet()) {
            System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());

        }*/
        /*
        //根据【省份名称、城市名称】获取区县边界
        Map<String, Map<String, String>> province2areas = readAllAreasByCity("北京市", "北京城区", path);
        for (Map.Entry<String, Map<String, String>> entry : province2areas.entrySet()) {
            System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
        }*/

        /*
        //根据【省份名称、城市名称、区县名称】获取区县边界
        String coords = readCoordsByArea("广东省", "中山市", "三角镇", path);
        System.out.println(coords);*/

        /*
        //根据【区县名称】获取区县边界
        String coords = getCoordsByAreaName("海淀区");
        System.out.println("coords: " + coords);*/

        /*
        Map<String, String> province2boundary = readSingleProvinceBoundaryJson(path, "北京市");
        for (Map.Entry<String, String> entry : province2boundary.entrySet()) {
            System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
        }*/

        Map.Entry<String, Map<String, String>> coords = getCoordsByCityName("北京市", "北京城区");
        System.out.println("key = " + coords.getKey() + ", value = " + coords.getValue());
        //System.out.println(coords.getValue());
    }

//    public static void main(String[] args) {
//        String targetFolder = "E:\\IdeaProjects\\zfzx-util\\src\\main\\resources\\";
//        //testWriteJson(targetFolder);
//        //testReadJson(targetFolder + "province-city-area");
//        //testWriteAllProvincesBoundaryJson(targetFolder + "province");
//        //testWriteAllCitiesBoundaryJson(targetFolder + "province-city");
//        //testReadJson(targetFolder + "province");
//        //testContainsPoint();
//        //testPolygonsIntersect();
//
//        String aa = "12.2,34.5;13.2,33.6|15.2,23.8;12.9,25.1";
//        //String[] aas = aa.split("|");
//        String[] aas = StringUtils.split(aa, "|");
//        System.out.println(aas.length);
//        for (int i = 0; i < aas.length; i++) {
//            String _aa = aas[i];
//            System.out.println(_aa);
//            String[] _aas = StringUtils.split(_aa, ";");
//            for (int j = 0; j < _aas.length; j++) {
//                System.out.println(_aas[j]);
//            }
//
//        }
//    }


    /******获取所有省份边界【start】******/
    public static Map<String, String> getAllProvincesBoundary() {
        Map<String, String> province2boundary = new HashMap<String, String>();
        String httpUrl = "https://restapi.amap.com/v3/config/district?keywords=中国&subdistrict=1&key=" + amapKey + "&extensions=base";
        System.out.println("httpUrl: " + httpUrl);
        String resStr = doGet(httpUrl);
        JSONObject json = JSONObject.parseObject(resStr);
        //System.out.println(json);
        String info = json.getString("info");
        if ("OK".equals(info)) {
            String adcode, name;
            JSONArray provinces = json.getJSONArray("districts").getJSONObject(0).getJSONArray("districts");
            for (int i = 0; i < provinces.size(); i++) {
                //for(int i = 0;i < 1;i++) {
                adcode = provinces.getJSONObject(i).getString("adcode");
                name = provinces.getJSONObject(i).getString("name");
                //System.out.println(adcode + "---" + name);
                String polyline = getSingleProvinceOrCityBoundaryByAdcode(adcode, name);
                province2boundary.put(name, polyline);
            }
        }
        return province2boundary;
    }

    public static String getSingleProvinceOrCityBoundaryByAdcode(String adcode, String provinceName) {
        String polyline = "";
        String path = "https://restapi.amap.com/v3/config/district?keywords=" + adcode + "&subdistrict=1&key=" + amapKey + "&extensions=all";
        System.out.println("httpUrl: " + path);
        String res = doGet(path);
        JSONObject json = JSONObject.parseObject(res);
        //System.out.println(json);
        String info = json.getString("info");
        if ("OK".equals(info)) {
            String _adcode, name;
            JSONArray jArray = json.getJSONArray("districts");
            if (jArray.size() == 0) {
                System.out.println("省份 --> " + provinceName + ": 无城市数据！");
            } else if (jArray.size() == 1) {
                polyline = jArray.getJSONObject(0).getString("polyline");
            } else if (jArray.size() > 1) {
                System.out.println("省份 --> " + provinceName + ": 检索出多条省份数据！");
            }
        }
        return polyline;
    }

    public static void writeAllProvincesOrCitiesBoundaryJson(String filePath, Map<String, String> province2boundary) {
        String jsonString = JSONUtils.toJSONString(province2boundary);
        JSONObject object = JSONObject.parseObject(jsonString);
        String pretty = JSON.toJSONString(object, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat);
        try {
            Writer write = new OutputStreamWriter(new FileOutputStream(filePath), "UTF-8");
            write.write(pretty);
            write.flush();
            write.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void testWriteAllProvincesBoundaryJson(String path) {
        String filePath = "";
        Map<String, String> province2boundary = getAllProvincesBoundary();
        for (Map.Entry<String, String> pbEntry : province2boundary.entrySet()) {
            filePath = path + File.separator + pbEntry.getKey() + ".json";
            Map<String, String> temp = new HashMap<>();
            temp.put(pbEntry.getKey(), pbEntry.getValue());
            writeAllProvincesOrCitiesBoundaryJson(filePath, temp);
        }
    }

    /*public static Map<String, String> readSingleProvinceBoundaryJson(String folder, String provinceName) {
        String provinceJsonFilePath = folder + File.separator + provinceName + ".json";
        Map<String, String> province2boundary = null;
        try {
            File file = new File(provinceJsonFilePath);
            String str = FileUtils.readFileToString(file, "UTF-8");
            province2boundary = JSONObject.parseObject(str, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return province2boundary;
    }*/

    /*public static Map<String, Map<String, String>> readAllProvincesBoundary(String path) {
        Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
        File file = new File(path);
        File[] fs = file.listFiles();
        for (File f : fs) {
            if (!f.isDirectory()) {
                String provinceName = f.getName();
                provinceName = provinceName.substring(0, provinceName.length() - 5);
                //System.out.println(provinceName);
                Map<String, String> province2boundary = readSingleProvinceBoundaryJson(path, provinceName);
                result.put(provinceName, province2boundary);
            }
        }
        return result;
    }*/

    public static Map<String, String> getProvinceBoundary(String provinceName) {
        return province2boundary.get(provinceName);
    }

    /******获取所有省份边界【end】******/


    /******获取所有城市边界【start】******/
    public static Map<String, Map<String, String>> getAllCitiesBoundary() {
        Map<String, Map<String, String>> province2citiesBoundary = new HashMap<String, Map<String, String>>();
        String httpUrl = "https://restapi.amap.com/v3/config/district?keywords=中国&subdistrict=1&key=" + amapKey + "&extensions=base";
        System.out.println("httpUrl: " + httpUrl);
        String resStr = doGet(httpUrl);
        JSONObject json = JSONObject.parseObject(resStr);
        //System.out.println(json);
        String info = json.getString("info");
        if ("OK".equals(info)) {
            String adcode, name;
            JSONArray provinces = json.getJSONArray("districts").getJSONObject(0).getJSONArray("districts");
            for (int i = 0; i < provinces.size(); i++) {
                //for(int i = 0;i < 1;i++) {
                adcode = provinces.getJSONObject(i).getString("adcode");
                name = provinces.getJSONObject(i).getString("name");
                //System.out.println(adcode + "---" + name);
                Map<String, String> res = getCitiesBoundaryByAdcode(adcode, name);
                province2citiesBoundary.put(name, res);
            }
        }
        return province2citiesBoundary;
    }

    public static Map<String, String> getCitiesBoundaryByAdcode(String adcode, String provinceName) {
        Map<String, String> city2boundary = new HashMap<String, String>();
        String path = "https://restapi.amap.com/v3/config/district?keywords=" + adcode + "&subdistrict=1&key=" + amapKey + "&extensions=base";
        System.out.println("httpUrl: " + path);
        String res = doGet(path);
        JSONObject json = JSONObject.parseObject(res);
        //System.out.println(json);
        String info = json.getString("info");
        if ("OK".equals(info)) {
            String _adcode, name;
            JSONArray jArray = json.getJSONArray("districts");
            if (jArray.size() == 0) {
                System.out.println("省份 --> " + provinceName + ": 无城市数据！");
            } else if (jArray.size() == 1) {
                JSONArray cities = jArray.getJSONObject(0).getJSONArray("districts");
                for (int i = 0; i < cities.size(); i++) {
                    _adcode = cities.getJSONObject(i).getString("adcode");
                    name = cities.getJSONObject(i).getString("name");
                    System.out.println(_adcode + "-------" + name);
                    String polyline = getSingleProvinceOrCityBoundaryByAdcode(_adcode, name);
                    city2boundary.put(name, polyline);
                }
            } else if (jArray.size() > 1) {
                System.out.println("省份 --> " + provinceName + ": 检索出多条省份数据！");
            }
        }
        return city2boundary;
    }

    public static void testWriteAllCitiesBoundaryJson(String path) {
        String filePath = "";
        Map<String, Map<String, String>> province2citiesBoundary = getAllCitiesBoundary();
        for (Map.Entry<String, Map<String, String>> pbEntry : province2citiesBoundary.entrySet()) {
            filePath = path + File.separator + pbEntry.getKey() + ".json";
            writeAllProvincesOrCitiesBoundaryJson(filePath, pbEntry.getValue());
        }
    }

    /*public static Map<String, String> readSingleCitiesBoundaryByProvince(String folder, String provinceName) {
        String provinceJsonFilePath = folder + File.separator + provinceName + ".json";
        Map<String, String> city2boundary = null;
        try {
            File file = new File(provinceJsonFilePath);
            String str = FileUtils.readFileToString(file, "UTF-8");
            city2boundary = JSONObject.parseObject(str, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return city2boundary;
    }*/

   /* public static Map<String, Map<String, String>> readAllProvinces2citiesBoundary(String path) {
        Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
        File file = new File(path);
        File[] fs = file.listFiles();
        for (File f : fs) {
            if (!f.isDirectory()) {
                String provinceName = f.getName();
                provinceName = provinceName.substring(0, provinceName.length() - 5);
                Map<String, String> city2boundary = readSingleCitiesBoundaryByProvince(path, provinceName);
                result.put(provinceName, city2boundary);
            }
        }
        return result;
    }*/

    public static Map<String, String> getAllCitiesBoundaryByProvince(String provinceName) {
        return province2citiesBoundary.get(provinceName);
    }
    /******获取所有城市边界【start】******/

    /**
     * 检查多边形是否包含了某点~多边形都是由点组成
     *
     * @param px 纬度
     * @param py 经度
     * @param xD 多边形所有纬度
     * @param yD 多边形所有经度
     * @return
     */
    public static boolean containsPoint(double px, double py, ArrayList<Double> xD, ArrayList<Double> yD) {
        int verticesCount = xD.size();
        int nCross = 0;
        for (int i = 0; i < verticesCount; ++i) {
            double ix = xD.get(i);
            double iy = yD.get(i);
            double i1x = xD.get((i + 1) % verticesCount);
            double i1y = yD.get((i + 1) % verticesCount);

            // 求解 y=p.y 与 p1 p2 的交点
            if (iy == i1y) {   // p1p2 与 y=p0.y平行
                continue;
            }
            if (py < Math.min(iy, i1y)) { // 交点在p1p2延长线上
                continue;
            }
            if (py >= Math.max(iy, i1y)) { // 交点在p1p2延长线上
                continue;
            }
            // 求交点的 X 坐标
            float x = (float) ((py - iy) * (i1x - ix)
                    / (i1y - iy) + ix);
            if (x > px) { // 只统计单边交点
                nCross++;
            }
        }
        // 单边交点为偶数，点在多边形之外
        return (nCross % 2 == 1);
    }

    public static void testContainsPoint() {

        double px = 39.24097, py = 117.05521;// false: 39.24097  117.05521 ||| true: 39.21707  117.17056
        ArrayList<Double> xD = new ArrayList<>();
        xD.add(39.35989);
        xD.add(39.18961);
        xD.add(39.20471);
        xD.add(39.01657);
        xD.add(39.13605);
        xD.add(39.23492);
        xD.add(39.3544);
        ArrayList<Double> yD = new ArrayList<>();
        yD.add(117.02774);
        yD.add(117.09229);
        yD.add(116.90826);
        yD.add(117.04834);
        yD.add(117.30927);
        yD.add(117.3587);
        yD.add(117.24335);

        System.out.println(containsPoint(px, py, xD, yD));
    }

    public static boolean isSegmentsIntersect(Point[] segA, Point[] segB) {
        Point segA0 = segA[0], segA1 = segA[1];
        Point segB0 = segB[0], segB1 = segB[1];
        double abc = (segA0.x - segB0.x) * (segA1.y - segB0.y) - (segA0.y - segB0.y) * (segA1.x - segB0.x);
        double abd = (segA0.x - segB1.x) * (segA1.y - segB1.y) - (segA0.y - segB1.y) * (segA1.x - segB1.x);
        if (abc * abd >= 0) {
            return false;
        }
        double cda = (segB0.x - segA0.x) * (segB1.y - segA0.y) - (segB0.y - segA0.y) * (segB1.x - segA0.x);
        double cdb = cda + abc - abd;
        return !(cda * cdb >= 0);
    }

    public static boolean isPolygonsIntersect(Point[] plyA, Point[] plyB) {
        for (int i = 0, il = plyA.length; i < il; i++) {
            for (int j = 0, jl = plyB.length; j < jl; j++) {
                Point[] segA = {plyA[i], plyA[i == il - 1 ? 0 : i + 1]};
                Point[] segB = {plyB[j], plyB[j == jl - 1 ? 0 : j + 1]};
                if (isSegmentsIntersect(segA, segB)) {
                    return true;
                }
            }
        }
        return false;
    }

    //判断点是否在另一平面图中
    public static boolean isPointInPolygon(Point point, Point[] polygon) {

        //下述代码来源：http://paulbourke.net/geometry/insidepoly/，进行了部分修改
        //基本思想是利用射线法，计算射线与多边形各边的交点，如果是偶数，则点在多边形外，否则
        //在多边形内。还会考虑一些特殊情况，如点在多边形顶点上，点在多边形边上等特殊情况。
        int N = polygon.length;
        boolean boundOrVertex = true; //如果点位于多边形的顶点或边上，也算做点在多边形内，直接返回true
        int intersectCount = 0; //cross points count of x
        double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
        Point p1, p2; //neighbour bound vertices
        Point p = point; //测试点

        p1 = polygon[0]; //left vertex
        for (int i = 1; i <= N; ++i) { //check all rays
            if (p.x == p1.x && p.y == p1.y) {
                return boundOrVertex; //p is an vertex
            }

            p2 = polygon[i % N]; //right vertex
            if (p.y < Math.min(p1.y, p2.y) || p.y > Math.max(p1.y, p2.y)) { //ray is outside of our interests
                p1 = p2;
                continue; //next ray left point
            }

            if (p.y > Math.min(p1.y, p2.y) && p.y < Math.max(p1.y, p2.y)) { //ray is crossing over by the algorithm (common part of)
                if (p.x <= Math.max(p1.x, p2.x)) { //x is before of ray
                    if (p1.y == p2.y && p.x >= Math.min(p1.x, p2.x)) { //overlies on a horizontal ray
                        return boundOrVertex;
                    }

                    if (p1.x == p2.x) { //ray is vertical
                        if (p1.x == p.x) { //overlies on a vertical ray
                            return boundOrVertex;
                        } else { //before ray
                            ++intersectCount;
                        }
                    } else { //cross point on the left side
                        double xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x; //cross point of x
                        if (Math.abs(p.x - xinters) < precision) { //overlies on a ray
                            return boundOrVertex;
                        }

                        if (p.x < xinters) { //before ray
                            ++intersectCount;
                        }
                    }
                }
            } else { //special case when ray is crossing through the vertex
                if (p.y == p2.y && p.x <= p2.x) { //p crossing over p2
                    Point p3 = polygon[(i + 1) % N]; //next vertex
                    if (p.y >= Math.min(p1.y, p3.y) && p.y <= Math.max(p1.y, p3.y)) { //p.y lies between p1.y & p3.y
                        ++intersectCount;
                    } else {
                        intersectCount += 2;
                    }
                }
            }
            p1 = p2; //next ray left point
        }

        if (intersectCount % 2 == 0) { //偶数在多边形外
            return false;
        } else { //奇数在多边形内
            return true;
        }
    }

    //判断两多变形是否存在点与区域的包含关系(A的点在B的区域内或B的点在A的区域内)
    public static boolean isPointInPolygonBidirectional(Point[] plyA, Point[] plyB) {//面面
        boolean a = false, b = false;
        for (int i = 0; i < plyA.length; i++) {
            if (isPointInPolygon(plyA[i], plyB)) {
                a = true;
                break;
            }
        }
        if (!a) {
            for (int i = 0; i < plyB.length; i++) {
                if (isPointInPolygon(plyB[i], plyA)) {
                    b = true;
                    break;
                }
            }
        }
        return a || b;
    }


    public static boolean isPolygonsOverlap(Point[] plyA, Point[] plyB) {
        return isPolygonsIntersect(plyA, plyB) || isPointInPolygonBidirectional(plyA, plyB);
    }

    /*public static void testPolygonsIntersect() {
        //true
        Point[] plyA = new Point[3];
        Point p1 = new Point();
        p1.x = 39.96655;
        p1.y = 116.34796;
        Point p2 = new Point();
        p2.x = 39.92054;
        p2.y = 116.30539;
        Point p3 = new Point();
        p3.x = 39.90612;
        p3.y = 116.38401;
        plyA[0] = p1;
        plyA[1] = p2;
        plyA[2] = p3;

        Point[] plyB = new Point[3];
        Point p4 = new Point();
        p4.x = 39.94663;
        p4.y = 116.40839;
        Point p5 = new Point();
        p5.x = 39.89342;
        p5.y = 116.32256;
        Point p6 = new Point();
        p6.x = 39.87659;
        p6.y = 116.39877;
        plyB[0] = p4;
        plyB[1] = p5;
        plyB[2] = p6;

        //false
        Point[] plyC = new Point[3];
        Point p7 = new Point();
        p7.x = 39.96277;
        p7.y = 116.34007;
        Point p8 = new Point();
        p8.x = 39.91779;
        p8.y = 116.31878;
        Point p9 = new Point();
        p9.x = 39.92672;
        p9.y = 116.35689;
        plyC[0] = p7;
        plyC[1] = p8;
        plyC[2] = p9;

        Point[] plyD = new Point[3];
        Point p10 = new Point();
        p10.x = 39.91196;
        p10.y = 116.41148;
        Point p11 = new Point();
        p11.x = 39.87179;
        p11.y = 116.37028;
        Point p12 = new Point();
        p12.x = 39.87865;
        p12.y = 116.43208;
        plyD[0] = p10;
        plyD[1] = p11;
        plyD[2] = p12;


        System.out.println(isPolygonsIntersect(plyA, plyB));
        System.out.println(isPolygonsIntersect(plyC, plyD));
    }*/


}
